package com.hup.windowUtil.presenter;

import com.hup.utils.jna.common.Win32Util;
import com.hup.windowUtil.model.WindowData;
import com.hup.windowUtil.view.MainFrame;
import com.sun.jna.platform.win32.User32;
import com.sun.jna.platform.win32.WinDef.HWND;
import com.sun.jna.platform.win32.WinDef.RECT;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.function.Supplier;

/**
 * @author hugan
 * @date 2021/9/1
 */
@Log4j2
@Component
public class MainPresenter {

    private String appTitle;

    public void startUp() {
        MainFrame mainFrame = new MainFrame();
        appTitle = mainFrame.getTitle();
        mainFrame.setVisible(true);
    }

    public List<WindowData> getWindowData() {
        ArrayList<HWND> windows = Win32Util.listWindow();
        List<WindowData> res = new ArrayList<>(windows.size());
        for (HWND hwnd : windows) {
            WindowData item = new WindowData();
            item.hwnd = hwnd;
            item.title = Win32Util.getWindowTitle(hwnd);
            if (Objects.equals(appTitle, item.title)) {
                //过滤本程序
                continue;
            }
            item.processPath = Win32Util.getProcessPath(hwnd);
            item.isOnTop = Win32Util.isWindowOnTop(hwnd);

            int style = User32.INSTANCE.GetWindowLong(hwnd, User32.GWL_STYLE);
            item.canResize = (style & User32.WS_THICKFRAME) != 0;
            item.canMax = (style & User32.WS_MAXIMIZEBOX) != 0;
            res.add(item);
        }
        return res;
    }

    public void execute(WindowData windowData, Supplier<Boolean> supplier) {
        if (windowData.title.contains("Microsoft Text Input Application")
                || windowData.title.contains("Program Manager")) {
            throw new IllegalArgumentException("不要搞系统窗口");
        }
        if (!supplier.get()) {
            throw new IllegalArgumentException("执行失败: 权限不足? 窗口不存在?");
        }
    }

    public void setOnTop(WindowData windowData, boolean isOnTop) {
        execute(windowData, () -> Win32Util.setWindowOnTop(windowData.hwnd, isOnTop));
    }

    /**
     * @param b true-添加样式
     * @param value 样式值
     */
    private void setWindowStyle(WindowData windowData, boolean b, int value) {
        execute(windowData, () -> {
            int style = User32.INSTANCE.GetWindowLong(windowData.hwnd, User32.GWL_STYLE);
            if (b) {
                style |= value;//位或; 添加样式
            } else {
                style &= ~value;// 先[位非,~], 再[位与] ; 移除样式
            }
            return User32.INSTANCE.SetWindowLong(windowData.hwnd, User32.GWL_STYLE, style) != 0;
        });
    }

    public void setCanResize(WindowData windowData, boolean b) {
        setWindowStyle(windowData, b, User32.WS_THICKFRAME);
    }

    public void setCanMax(WindowData windowData, boolean b) {
        setWindowStyle(windowData, b, User32.WS_MAXIMIZEBOX);
    }

    public void setSize(WindowData windowData, int width, int height) {
        execute(windowData, () -> Win32Util.setWindowSize(windowData.hwnd, width, height));
    }

    public void getSize(WindowData windowData) {
        execute(windowData, () -> {
            if (windowData.rect == null) windowData.rect = new RECT();
            RECT rect = windowData.rect;
            boolean res = Win32Util.getWindowRect(windowData.hwnd, rect);
            if (res) {
                windowData.width = rect.right - rect.left;
                windowData.height = rect.bottom - rect.top;
            }
            return res;
        });
    }

}
